package cc.uncarbon.module.appapi.service;

import cc.uncarbon.framework.core.context.UserContext;
import cc.uncarbon.framework.core.context.UserContextHolder;
import cc.uncarbon.framework.core.exception.BusinessException;
import cc.uncarbon.module.appapi.config.WechatPayConfig;
import cc.uncarbon.module.appapi.util.RequestUtils;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.exception.HttpException;
import com.wechat.pay.java.core.exception.MalformedMessageException;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.partnerpayments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.*;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Amount;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.*;
import com.yanrumiao.entity.ItemEntity;
import com.yanrumiao.entity.OrdersEntity;
import com.yanrumiao.entity.PaymentEntity;
import com.yanrumiao.entity.StoreEntity;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;


/**
 * 微信支付
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class WechatPayService {



    private final WechatPayConfig wechatPayConfig;
    private final RSAAutoCertificateConfig rsaConfig;



    @Transactional(rollbackFor = Exception.class)
    public PrepayWithRequestPaymentResponse unifiedOrderV3(OrdersEntity orders, ItemEntity itemEntity,StoreEntity store) {

        // 获取 openid
        String openId = getOpenIdFromUserContext();
        if (openId == null || openId.isEmpty()) {
            throw new BusinessException(400, "用户未绑定微信 OpenID");
        }
        if (store == null) {
            throw new BusinessException(400, "店铺不存在");
        }
        JsapiServiceExtension jsapiService = new JsapiServiceExtension.Builder().config(rsaConfig).build();
        // 校验 wechatPayConfig 字段是否为空
        validateWechatPayConfig(wechatPayConfig);
        int money = orders.getPayMoney().multiply(new BigDecimal(100)).intValueExact();
        try {
            //构建预支付请求
            PrepayRequest request = new PrepayRequest();
            Amount amount = new Amount();
            amount.setTotal(money);
            request.setAmount(amount);
            request.setSpAppid(wechatPayConfig.getAppid());
            request.setSpMchid(wechatPayConfig.getMchId());
            request.setSubMchid(store.getStoreMchid());
            request.setDescription(itemEntity.getName());
            request.setOutTradeNo(orders.getOrderNo());
            request.setNotifyUrl(wechatPayConfig.getNotifyUrl());
            Payer payer = new Payer();
            payer.setSpOpenid(openId);
            request.setPayer(payer);
            log.info("发起预支付请求: {}", request);

            PrepayWithRequestPaymentResponse prepay = jsapiService.prepayWithRequestPayment(request, wechatPayConfig.getAppid());

            return prepay;
        } catch (HttpException e) {
            log.error("发送HTTP请求失败", e); //
            throw new BusinessException(500, "发送HTTP请求失败");
        } catch (ServiceException e) {
            log.error("服务异常", e); // 记录异常信息
            throw new BusinessException(500, "服务异常");
        } catch (MalformedMessageException e) {
            log.error("返回体类型不合法，或者解析返回体失败", e); // 记录异常信息
            throw new BusinessException(500, "返回体类型不合法，或者解析返回体失败");
        }

    }

    private String getOpenIdFromUserContext() {
        UserContext userContext = UserContextHolder.getUserContext();
        if (userContext == null || userContext.getExtraData() == null) {
            return null;
        }
        Object openIdObj = userContext.getExtraData().get("openId");
        if (openIdObj instanceof String) {
            return (String) openIdObj;
        }
        return null; // 如果类型不匹配，返回 null
    }

    private void validateWechatPayConfig(WechatPayConfig wechatPayConfig) {
        if (wechatPayConfig.getMchId() == null || wechatPayConfig.getMchId().isEmpty()) {
            throw new IllegalArgumentException("Merchant ID cannot be null or empty");
        }
        if (wechatPayConfig.getSerialNo() == null || wechatPayConfig.getSerialNo().isEmpty()) {
            throw new IllegalArgumentException("Merchant Serial Number cannot be null or empty");
        }
        if (wechatPayConfig.getCertPath() == null || wechatPayConfig.getCertPath().isEmpty()) {
            throw new IllegalArgumentException("Certificate Path cannot be null or empty");
        }
        if (wechatPayConfig.getApiKey() == null || wechatPayConfig.getApiKey().isEmpty()) {
            throw new IllegalArgumentException("API Key cannot be null or empty");
        }
        if (wechatPayConfig.getAppid() == null || wechatPayConfig.getAppid().isEmpty()) {
            throw new IllegalArgumentException("App ID cannot be null or empty");
        }
        if (wechatPayConfig.getNotifyUrl() == null || wechatPayConfig.getNotifyUrl().isEmpty()) {
            throw new IllegalArgumentException("Notify URL cannot be null or empty");
        }
    }

    //支付成功的回调
    public Transaction payNotify(HttpServletRequest request) {

        //1.回调通知的验签与解密
        String wechatPaySerial = request.getHeader("Wechatpay-Serial");
        String nonce = request.getHeader("Wechatpay-Nonce");
        String timestamp = request.getHeader("Wechatpay-Timestamp");
        String signature = request.getHeader("Wechatpay-Signature");
        String requestBody = RequestUtils.readData(request);
        log.info("---------支付成功的回调");
        //2.构造 RequestParam
        RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(wechatPaySerial)
                .nonce(nonce)
                .signature(signature)
                .timestamp(timestamp)
                .body(requestBody)
                .build();
        //3.初始化 NotificationParser
        NotificationParser parser = new NotificationParser(rsaConfig);
        //4.以支付通知回调为例，验签、解密并转换成 Transaction
        Transaction transaction = parser.parse(requestParam, Transaction.class);
       return transaction;

    }

    public Status refund(OrdersEntity orders,PaymentEntity payment,StoreEntity store) {

        //请求微信支付相关配置
        RefundService service = new RefundService.Builder()
                .config(rsaConfig).build();
        //获取商户信息
        AmountReq amountReq = new AmountReq();

        BigDecimal payMoney = orders.getPayMoney().multiply(new BigDecimal("100"));
        log.info("------rrr");
        amountReq.setTotal(payMoney.longValueExact());
        amountReq.setRefund(payMoney.longValueExact());
        amountReq.setCurrency("CNY");

        CreateRequest request = new CreateRequest();
        request.setSubMchid(store.getStoreMchid());
        request.setAmount(amountReq);
        request.setOutTradeNo(orders.getOrderNo());
        request.setOutRefundNo(orders.getOrderNo());
        request.setNotifyUrl(wechatPayConfig.getRefundUrl());
        try {
            Refund refund = service.create(request);
            return refund.getStatus();
        } catch (Exception e) {
            log.error("---------退款失败" + e.getMessage());
            throw new BusinessException(500, "退款失败");
        }
    }

    public void close(OrdersEntity orders,StoreEntity store) {
        CloseOrderRequest request = new CloseOrderRequest();
        //获取商户信息
        JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(rsaConfig).signType("RSA").build();
        request.setOutTradeNo(orders.getOrderNo());
        request.setSpMchid(wechatPayConfig.getMchId());
        request.setSubMchid(store.getStoreMchid());
        service.closeOrder(request);
    }

    public Transaction queryOrderById(OrdersEntity orders, StoreEntity store) {
        QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
        request.setSpMchid(wechatPayConfig.getMchId());
        request.setOutTradeNo(orders.getOrderNo());
        request.setSubMchid(store.getStoreMchid());
        JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(rsaConfig).signType("RSA").build();
        Transaction transaction = service.queryOrderByOutTradeNo(request);
       return transaction;
    }


    //退款回调
    public RefundNotification refundNotify(HttpServletRequest request) {
        //1.回调通知的验签与解密
        String wechatPaySerial = request.getHeader("Wechatpay-Serial");
        String nonce = request.getHeader("Wechatpay-Nonce");
        String timestamp = request.getHeader("Wechatpay-Timestamp");
        String signature = request.getHeader("Wechatpay-Signature");
        String requestBody = RequestUtils.readData(request);
        //2.构造 RequestParam
        RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(wechatPaySerial)
                .nonce(nonce)
                .signature(signature)
                .timestamp(timestamp)
                .body(requestBody)
                .build();
        //3.初始化 NotificationParser
        log.info("---------退款回调" );
        NotificationParser parser = new NotificationParser(rsaConfig);
        //4.以支付通知回调为例，验签、解密并转换成 Transaction
        RefundNotification transaction = parser.parse(requestParam, RefundNotification.class);
        log.info("---------退款回调11"+transaction );
        return transaction;
    }
}